package day17;
/*本类用于测试单例设计模式 2 - 懒汉式--面试重点!!!*/
/*总结:
* 关于单例设计模式的两种实现方式:
* 1.饿汉式 : 不管你用不用这个类的对象,都会直接先创建一个
* 2.懒汉式 : 先不给你创建这个类的对象,等你需要的时候再帮你创建--利用了延迟加载的思想
* 延迟加载的思想:是指不会在第一时间就把对象创建好来占用内存,而是什么时候用到,什么时候再去创建对象
* 3.线程安全问题 : 是指共享资源有线程并发的数据安全隐患,可以通过加锁的方式[同步代码块/同步方法]
* */
public class Singleton2 {
    public static void main(String[] args) {
        //6.创建对象进行测试
        MySingle2 s1 = MySingle2.getMySingle2();
        MySingle2 s2 = MySingle2.getMySingle2();
        System.out.println( s1 == s2 );//true,比较的是地址值,说明是同一个对象
        System.out.println( s1 );//cn.tedu.single.MySingle2@1b6d3586
        System.out.println( s2 );//cn.tedu.single.MySingle2@1b6d3586
    }
}
//0.创建单例程序
class MySingle2{
    //1.私有化构造方法,为了防止外部调用构造方法直接创建本类对象
    private MySingle2(){}
    //2.在类的内部创建好引用类型变量(延迟加载的思想)--注意私有化
    //5.2本处的引用类型变量也需要修饰成static的,因为静态只能调用静态,getMySingle2()是静态方法
    static private MySingle2 single2;
    //7.2.2同步代码块中使用的唯一的锁对象
    static Object o = new Object();
    /*问题:程序中有共享资源single2,并且有多条语句(3句)操作了共享资源
    * 此时single2共享资源在多线程环境下一定会存在多线程数据安全隐患
    * 解决方案1:同步代码块[加锁,范围是操作共享资源的所有代码]
    * 解决方案2:同步方法[如果方法中的所有代码都需要被同步,那么这个方法可以修饰成同步方法]
    * 注意事项:锁对象在静态方法中,不可以使用this,因为静态资源优先于对象加载
    * 锁对象可以使用外部创建好的唯一的锁对象o,但请注意,需要是静态的,静态只能调用静态
    * */
    //3.对外提供公共的全局访问点
    //5.1注意要使用static来修饰本公共方法,为了方便后续可以通过类名直接调用
    //7.1将方法修饰成同步方法
    synchronized static public MySingle2 getMySingle2(){
        //4.当用户调用此方法时,才说明用到这个对象了,那么我们就把这个对象返回
        /*注意:这里需要增加一个判断
        如果调用方法时single2的值为null,说明之前没有new过,保存的是默认值
        这时才需要new对象,如果single2的值不为null,直接return single2即可*/
        //7.2可以将操作共享资源的多条语句放入同步代码块之中
        synchronized (o) {
        //synchronized (this) {
            if (single2 == null) {
                single2 = new MySingle2();//没有对象时才创建对象,并赋值给single2
            }
            return single2;//有对象则直接返回single2
        }
    }



}